package com.zoweunion.mechanic.controller;

import com.jhlabs.image.PixelUtils;
import net.coobird.thumbnailator.Thumbnails;

import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.awt.image.ColorModel;
import java.awt.image.Kernel;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Hashtable;
import java.util.List;
import java.util.Random;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Semaphore;

public class MyGaussianFilter {
    public static int CLAMP_EDGES = 1;
    public static int WRAP_EDGES = 2;
    protected Kernel kernel;
    protected boolean alpha = false;
    protected boolean premultiplyAlpha = false;

    protected float radius;

    public MyGaussianFilter() {
        this(2.0F);
    }

    public MyGaussianFilter(float radius) {
        this.setRadius(radius);
    }

    public void setRadius(float radius) {
        this.radius = radius;
        this.kernel = makeKernel(radius);
    }

    public float getRadius() {
        return this.radius;
    }

    public BufferedImage filter(BufferedImage src, BufferedImage dst) {
        int width = src.getWidth();
        int height = src.getHeight();
        if (dst == null) {
            dst = this.createCompatibleDestImage(src, (ColorModel) null);
        }

        int[] inPixels = new int[width * height];
        int[] outPixels = new int[width * height];
        src.getRGB(0, 0, width, height, inPixels, 0, width);
        if (this.radius > 0.0F) {
            //这里是对图片进行处理
            convolveAndTranspose(this.kernel, inPixels, outPixels, width, height, this.alpha, this.alpha && this.premultiplyAlpha, false, CLAMP_EDGES, 1);
            convolveAndTranspose(this.kernel, outPixels, inPixels, height, width, this.alpha, false, this.alpha && this.premultiplyAlpha, CLAMP_EDGES, 2);

        }

        dst.setRGB(0, 0, width, height, inPixels, 0, width);
        return dst;
    }


    public BufferedImage createCompatibleDestImage(BufferedImage src, ColorModel dstCM) {
        if (dstCM == null) {
            dstCM = src.getColorModel();
        }

        return new BufferedImage(dstCM, dstCM.createCompatibleWritableRaster(src.getWidth(), src.getHeight()), dstCM.isAlphaPremultiplied(), (Hashtable) null);
    }

    public static Kernel makeKernel(float radius) {
        int r = (int) Math.ceil((double) radius);
        int rows = r * 2 + 1;
        float[] matrix = new float[rows];
        float sigma = radius / 3.0F;
        float sigma22 = 2.0F * sigma * sigma;
        float sigmaPi2 = 6.2831855F * sigma;
        float sqrtSigmaPi2 = (float) Math.sqrt((double) sigmaPi2);
        float radius2 = radius * radius;
        float total = 0.0F;
        int index = 0;

        int i;
        for (i = -r; i <= r; ++i) {
            float distance = (float) (i * i);
            if (distance > radius2) {
                matrix[index] = 0.0F;
            } else {
                matrix[index] = (float) Math.exp((double) (-distance / sigma22)) / sqrtSigmaPi2;
            }

            total += matrix[index];
            ++index;
        }

        for (i = 0; i < rows; ++i) {
            matrix[i] /= total;
        }

        return new Kernel(rows, 1, matrix);
    }

    public static void convolveAndTranspose(Kernel kernel, int[] inPixels, int[] outPixels, int width, int height, boolean alpha, boolean premultiply, boolean unpremultiply, int edgeAction,
                                            int type) {
        try{
        float[] matrix = kernel.getKernelData((float[]) null);
        int cols = kernel.getWidth();
        int cols2 = cols / 2;
        int y = 0;

        if (type == 2) {
            y = height - 230;

        }

        for (; y < height; ++y) {
            int index = y;
            int ioffset = y * width;

            int length = width;
            for (int x = 0; x < length; ++x) {
                float r = 0.0F;
                float g = 0.0F;
                float b = 0.0F;
                float a = 0.0F;
                int moffset = cols2;

                int ia;
                int ix;
                int rgb;
                for (ia = -cols2; ia <= cols2; ++ia) {
                    float f = matrix[moffset + ia];
                    if (f != 0.0F) {
                        ix = x + ia;
                        if (ix < 0) {
                            if (edgeAction == CLAMP_EDGES) {
                                ix = 0;
                            } else if (edgeAction == WRAP_EDGES) {
                                ix = (x + width) % width;
                            }
                        } else if (ix >= width) {
                            if (edgeAction == CLAMP_EDGES) {
                                ix = width - 1;
                            } else if (edgeAction == WRAP_EDGES) {
                                ix = (x + width) % width;
                            }
                        }

                        rgb = inPixels[ioffset + ix];
                        int pa = rgb >> 24 & 255;
                        int pr = rgb >> 16 & 255;
                        int pg = rgb >> 8 & 255;
                        int pb = rgb & 255;
                        if (premultiply) {
                            float a255 = (float) pa * 0.003921569F;
                            pr = (int) ((float) pr * a255);
                            pg = (int) ((float) pg * a255);
                            pb = (int) ((float) pb * a255);
                        }

                        a += f * (float) pa;
                        r += f * (float) pr;
                        g += f * (float) pg;
                        b += f * (float) pb;
                    }
                }

                if (unpremultiply && a != 0.0F && a != 255.0F) {
                    float f = 255.0F / a;
                    r *= f;
                    g *= f;
                    b *= f;
                }

                ia = alpha ? PixelUtils.clamp((int) ((double) a + 0.5D)) : 255;
                int ir = PixelUtils.clamp((int) ((double) r + 0.5D));
                ix = PixelUtils.clamp((int) ((double) g + 0.5D));
                rgb = PixelUtils.clamp((int) ((double) b + 0.5D));
                if (type == 2) {
                    if (x < length - 100) {
                        outPixels[index] = outPixels[index];
                    } else {
                        outPixels[index] = ia << 24 | ir << 16 | ix << 8 | rgb;
                    }
                } else {
                    if (x < length - 230) {
                        outPixels[index] = outPixels[index];
                    } else {
                        outPixels[index] = ia << 24 | ir << 16 | ix << 8 | rgb;
                    }
                }

                index += height;
            }
        }
        }catch (Exception e){
            e.printStackTrace();
        }


    }

    public static void overlapImage(String newPicturePath, String waterMark) {
        try {
            BufferedImage big = ImageIO.read(new File(newPicturePath));
            Graphics2D gd = big.createGraphics();
            gd.setBackground(Color.white);
            gd.setColor(Color.white);
            gd.dispose();
            BufferedImage small = ImageIO.read(new File(waterMark));
            Graphics2D g = big.createGraphics();
            int x = big.getWidth() - 190;
            int y = big.getHeight() - 70;
            g.drawImage(small, x, y, small.getWidth(), small.getHeight(), null);
            g.dispose();
            ImageIO.write(big, "jpg", new File(newPicturePath));
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public static void addHotNewsWatrmark(){
        String rootPath = "D:\\nginx-1.15.5\\html\\web-mechanic\\upload\\news",
                waterMark = "D:\\nginx-1.15.5\\html\\web-mechanic\\upload\\watermark\\watermark.png";
        addChushouOrHotNewsWatermark(rootPath, waterMark);
        System.out.println("news 结束");
    }
    public static void addChushouWatermark(){
        String rootPath = "D:\\nginx-1.15.5\\html\\web-mechanic\\upload\\chushou",
                waterMark = "D:\\nginx-1.15.5\\html\\web-mechanic\\upload\\watermark\\watermark.png";
//        String rootPath = "/Users/beck/Documents/work/zhlh/material/app/chushou",
//                waterMark = "/Users/beck/Documents/work/zhlh/material/app/watermark.png";
        addChushouOrHotNewsWatermark(rootPath, waterMark);
        System.out.println("chushou 结束");
    }


    /**
     * chushou加水印
     */
    public static void addChushouOrHotNewsWatermark(String rootPath, String waterMark) {
        MyGaussianFilter gaussianFilter = new MyGaussianFilter();
        List<String> pictureList = getFilePath(rootPath);
        int pageSize = 2000;
        int threadNum = pictureList.size() / pageSize + 1;
        CountDownLatch countDownLatch = new CountDownLatch(threadNum);
        Semaphore semaphore = new Semaphore(50);
        System.out.println("创建线程数：" + threadNum);
        ExecutorService executorService = Executors.newCachedThreadPool();
        for (int i = 0; i < threadNum; i++) {
            List<String> subPictureList;
            if (i == threadNum - 1) {
                subPictureList = pictureList.subList(i * pageSize, pictureList.size());
            } else {
                subPictureList = pictureList.subList(i * pageSize, (i + 1) * pageSize);
            }
            executorService.execute(new Thread(() -> {
                try {
                    semaphore.acquire();
                    attachWaterMark(gaussianFilter, subPictureList, rootPath, waterMark);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                } finally {
                    semaphore.release();
                    countDownLatch.countDown();
                }
            }));
        }
        try {
            System.out.println("await");
            countDownLatch.await();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    private static void attachWaterMark(MyGaussianFilter gaussianFilter, List<String> subPictureList, String rootPath, String waterMark){
        BufferedImage fromImage = null;
        for (String picturePath : subPictureList) {
            //绝对路径
            String readPath = picturePath;
            //文件名
            String fileName = getFileName(readPath);
            String subReadPath = fileName.substring(0, 4);
            if (!subReadPath.equals("thum")) {
                try {
                    File file = new File(readPath);
                    fromImage = ImageIO.read(file);
                    BufferedImage toImage = new BufferedImage(fromImage.getWidth(), fromImage.getHeight(), BufferedImage.TYPE_INT_RGB);
                    gaussianFilter.setRadius(50);
                    gaussianFilter.filter(fromImage, toImage);
                    ImageIO.write(toImage, "jpg", new File(readPath));
                    overlapImage(readPath, waterMark);
                    System.out.println("水印大图绘制成功");
                } catch (IOException e) {
                    e.printStackTrace();
                }
            } else {
                System.out.println("这是小图");
            }
        }
    }

    /**
     * other加水印
     */
    public static void addOtherWatermark() {
        MyGaussianFilter gaussianFilter = new MyGaussianFilter();
        BufferedImage fromImage = null;
        String rootPath = "D:\\nginx-1.15.5\\html\\web-mechanic\\upload\\avatar\\others";
        String waterMark = "D:\\nginx-1.15.5\\html\\web-mechanic\\upload\\watermark\\watermark.png";
        List<String> folderList = getFolderPath(rootPath);
        int pageSize = 30;
        int threadNum = folderList.size() / pageSize + 1;
        CountDownLatch countDownLatch = new CountDownLatch(threadNum);
        Semaphore semaphore = new Semaphore(50);
        System.out.println("others 创建线程数：" + threadNum);
        ExecutorService executorService = Executors.newCachedThreadPool();
        for (int i = 0; i < threadNum; i++) {
            List<String> subFolderList;
            if (i == threadNum - 1) {
                subFolderList = folderList.subList(i * pageSize, folderList.size());
            } else {
                subFolderList = folderList.subList(i * pageSize, (i + 1) * pageSize);
            }
            executorService.execute(new Thread(() -> {
                for (String folder : subFolderList) {
                    try {
                        semaphore.acquire();
                        List<String> pictureList = getFilePath(folder);
                        attachWaterMark(gaussianFilter, pictureList, folder, waterMark);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    } finally {
                        semaphore.release();
                        countDownLatch.countDown();
                    }
                }
            }));
        }
        try {
            countDownLatch.await();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("others结束");
    }

    //遍历文件夹,得到所有图片
    public static List<String> getFilePath(String filePath) {
        List<String> pictureList = new ArrayList();
        File file = new File(filePath);
        if (file.isDirectory()) {
            File[] listFiles = file.listFiles();
            for (File image : listFiles) {
                pictureList.add(image.getAbsolutePath());
            }
            return pictureList;
        }
        return pictureList;
    }

    //遍历获取所有文件夹
    public static List<String> getFolderPath(String filePath) {
        List<String> folderList = new ArrayList();
        File file = new File(filePath);
        if (file.isDirectory()) {
            File[] listFiles = file.listFiles();
            for (File folder : listFiles) {
                folderList.add(folder.getAbsolutePath());
            }
            return folderList;
        }
        return folderList;
    }

    //获取文件名字
    public static String getFileName(String path) {
        String[] strings = path.split("\\\\");
        String string = strings[strings.length - 1];
        return string;
    }

    public static void addWatermark(String picturePath,String thumPicturePath) {
        MyGaussianFilter gaussianFilter = new MyGaussianFilter();
        BufferedImage fromImage = null;
        //水印的地址
        String waterMark = "D:\\nginx-1.15.5\\html\\web-mechanic\\upload\\watermark\\watermark.png";
        String readPath = picturePath;
        try {
            fromImage = ImageIO.read(new File(readPath));
            BufferedImage toImage = new BufferedImage(fromImage.getWidth(), fromImage.getHeight(), BufferedImage.TYPE_INT_RGB);
            gaussianFilter.setRadius(50);
            gaussianFilter.filter(fromImage, toImage);
            ImageIO.write(toImage, "jpg", new File(readPath));
            overlapImage(readPath, waterMark);
            System.out.println("水印大图绘制成功");
            Thumbnails.of(readPath).size(130, 100).toFile(thumPicturePath);
            System.out.println("缩略图绘制成功");
        } catch (IOException e) {
            e.printStackTrace();
        }
        System.out.println("结束");

    }

    public static void main(String[] args) {
        //chushou加水印
//        addChushouWatermark();
        // 增加新闻水印
//        addHotNewsWatrmark();
        //other加水印
        //addOtherWatermark();
        //System.out.println(getFileName("E:\\others\\20190601"));
        //addWatermark("E:\\新建文件夹\\1572260891212.jpg","E:\\新建文件夹\\thum_1572260891212.jpg");
    }
}
